import { _decorator, Component, EventTouch, instantiate, isValid, Node, Prefab, Sprite, UITransform, v3, Vec2, Vec3 } from 'cc'
import { ResMgr } from './ResMgr'
import { Bundle } from '../enum/Bundle'
import { Goods } from '../game/Goods'
import { EventMgr } from './EventMgr'
import { EventType } from '../enum/EventType'
import { ShelveLocker } from '../game/ShelveLocker'
import { ShelveBase } from '../scriptBase/ShelveBase'
import { Mode, ModeName, ModeType } from '../enum/Mode'
import { StorageUtil } from '../util/StorageUtil'
import { ObjUtil } from '../util/ObjUtil'
import { AudioMgr } from './AudioMgr'
import { PREVIEW } from 'cc/env'
import { GameUtil } from '../util/GameUtil'
const { ccclass, property } = _decorator

const PickOffset: number = 80

@ccclass('Manager/GameMgr')
export class GameMgr extends Component {

    private static _inst: GameMgr = null
    private static _node: Node = null
    private static _uiTrans: UITransform = null

    public static titleArr = ["气球", "童年玩具", "糖葫芦", "烧烤"];

    public static get Stage(): Node {
        return this._node.children[0]
    }

    public static gameData:GameUserData;

    /**已收集素材数组 */
    public static shopItemArr: number[] = [];
    
    /**通关时间 */
    public static curPassDay:number = 0;

    /**是否夜色背景 */
    public static isBlackBg:boolean = false;

    private static curLevel: object = {}
    public static get CurLevel(): number {
        if (!ObjUtil.has(this.curLevel, this.modeType)) return 0
        return this.curLevel[this.modeType]
    }

    public static get CurPassedLevel(): number {
        let passCnt: number = 0
        for (const mode in this.curLevel) {
            if (Object.prototype.hasOwnProperty.call(this.curLevel, mode)) {
                const level = this.curLevel[mode]
                passCnt += level
            }
        }
        return passCnt
    }


    public static get isHardLevel(): boolean {
        //todo 暂时屏蔽
        //return false;
        return (this.CurLevel + 1) > 1
    }

    private static unlockedMode: Mode[] = []
    public static mode: Mode = Mode.tp          //当天开启模式

    public static modeType: ModeType = ModeType.caiping       //选择的模式

    public static selectLev: number = 0      //选中的光卡

    /**当前阵营数量 1 单人 2双人 3三人 */
    public static gameCampSum: number = 1      

    /** 当前回合 0红，1蓝，2黄 */
    public static gameCampCur: number = 0   

    /**统计 当前阵营胜利次数 */
    public static gameCampWin:number[] = [0,0,0];

    private static _pickedGoods: Goods = null
    private static _holdGoods: Node = null

    public static shelveArr: ShelveBase[] = []
    public static shelveLockerArr: ShelveLocker[] = []

    //*正确顺序的道具ID */
    public static rightGoodId: number[] = [];

    /**初始道具ID数组 */
    public static goodsArr: number[] = []

    /**初始道具ID数组 下方拖拽位置 */
    public static goodsArrInit: number[] = []

    public static goodsData = {}

    /**步数 */
    public static stepNum:number =  0;

    /**验证次数 */
    public static sureNum:number =  0;

    /**正确数量 */
    public static rightMaxNum:number =  0;

    /**使用时间 */
    public static useTime:number =  0;

    /**状态 0正常游戏，1提示选择中，2透视选择中 */
    public static itemStatu:number =  0;

    private static pause: boolean = false
    public static get Pause(): boolean {
        return this.pause
    }
    public static set Pause(v: boolean) {
        this.pause = v;
        EventMgr.emit(EventType.Pause, v)
    }

    protected onLoad(): void {
        globalThis.GameMgr = GameMgr
        GameMgr._inst = this
        GameMgr._node = this.node
        GameMgr._uiTrans = this.getComponent(UITransform)

        this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this)
        this.node.on(Node.EventType.TOUCH_END, this.onTouchFinish, this)
        this.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchFinish, this)

        //GameMgr.resetGameLevle();

        GameMgr.unlockedMode = StorageUtil.getObj('unlockedMode', [0])
        GameMgr.curLevel = StorageUtil.getObj('curLevel', { 0: 0 })
        GameMgr.shopItemArr = StorageUtil.getObj('shopItemArr', []);

        GameMgr.curPassDay = StorageUtil.getItem('curPassDay', 0);

        GameMgr.gameData = StorageUtil.getObj('gameUserData', new GameUserData());
    }

    public static unlockMode(mode: Mode): void {
        if (this.unlockedMode.includes(mode)) return
        this.unlockedMode.push(mode)
        this.unlockedMode.sort()
        StorageUtil.setObj('unlockedMode', this.unlockedMode)
        EventMgr.emit(EventType.ModeUnlocked)
    }

    private static createStage(): void {
        const stagePre: Prefab = ResMgr.getRes(Bundle.Game, 'Stage')
        const stageNode: Node = instantiate(stagePre)
        this._node.addChild(stageNode)
    }

    public static startGame(): void {
        this.reset()
        this._node.destroyAllChildren()
        this._inst.scheduleOnce(() => {
            this.createStage()
        })
    }

    public static passGame(): void {
        if (!ObjUtil.has(this.curLevel, this.modeType)) {
            this.curLevel[this.modeType] = 0
        }
        this.curLevel[this.modeType]++
        StorageUtil.setObj('curLevel', this.curLevel)
        // if (this.curLevel[this.modeType] > 1){
        //     GameMgr.curPassDay = GameUtil.getYearToday();
        //     StorageUtil.setItem('curPassDay', GameMgr.curPassDay);
        // }
        // if (this.mode === Mode.tp && this.curLevel[this.mode] >= 15) {
        //     this.unlockMode(Mode.gs)
        // } else if (this.mode === Mode.gs && this.curLevel[this.mode] >= 10) {
        //     this.unlockMode(Mode.ls)
        // }
    }

    /**重置当前关卡 */
    public static resetGameLevle(): void {
        if (!ObjUtil.has(this.curLevel, this.modeType)) {
            this.curLevel[this.modeType] = 0
        }
        this.curLevel[this.modeType] = 0
        StorageUtil.setObj('curLevel', this.curLevel)
    }

    public static quitGame(): void {
        this._node.destroyAllChildren()
        this.reset()
    }

    public static pick(goods: Goods, uiPos: Vec2): void {
        this._pickedGoods = goods
        this._holdGoods = new Node()
        const sp: Sprite = this._holdGoods.addComponent(Sprite)
        sp.spriteFrame = goods.Sp.spriteFrame
        this._node.addChild(this._holdGoods)
        uiPos.y += PickOffset
        const localPos: Vec3 = GameMgr._uiTrans.convertToNodeSpaceAR(v3(uiPos.x, uiPos.y, 0))
        this._holdGoods.setPosition(localPos)
        AudioMgr.playSfx('点击消除物')
    }

    public static getShelveNodeById(id:number){
         for (let i = 0; i < this.shelveArr.length; i++) {
            const shelve: ShelveBase = this.shelveArr[i]
            if (shelve.Id == id){
                return shelve;
            }
         }
         return null;
    }

    public static release(): void {
        let isSuccess: boolean = false
        const holdGoodsWorldPos: Vec3 = this._holdGoods.getWorldPosition()
        for (let i = 0; i < this.shelveArr.length; i++) {
            const shelve: ShelveBase = this.shelveArr[i]
            if (shelve.getComponentInChildren(ShelveLocker)) continue
            const uiTrans: UITransform = shelve.getComponent(UITransform)
            const shelveWorldPos: Vec3 = shelve.node.getWorldPosition()
            const goodsLocalPos: Vec3 = uiTrans.convertToNodeSpaceAR(holdGoodsWorldPos)
            const disX: number = Math.abs(shelveWorldPos.x - holdGoodsWorldPos.x)
            const disY: number = Math.abs(shelveWorldPos.y - holdGoodsWorldPos.y)
            if (disX < uiTrans.width / 2 && disY < uiTrans.height / 2) {
                const slotId: number = 0 //shelve.getSlot(goodsLocalPos)
                // if (slotId < 0 || shelve.isSlotOccupied(slotId)) break

                let pickId = this._pickedGoods.Id;
                if ( shelve.isSlotOccupied(slotId)){
                    //需要位置交换
                    if (this._pickedGoods.comShelveId == -1){
                        //不允许拖到有物品的格子上
                        break;
                    }
                    let pickShelve = GameMgr.getShelveNodeById(this._pickedGoods.comShelveId);
                    if (pickShelve){
                        pickShelve.placeGoods(shelve.GoodsIdArr[0],0)
                        this._pickedGoods.Visible = true
                    }
                }else{
                    //直接拖动
                }
                if (this._pickedGoods.comShelveId == -1){
                    EventMgr.emit(EventType.RefreshInitBox)
                }
                const goodsId: number = pickId
                shelve.placeGoods(goodsId, slotId)
                isSuccess = true
                break
            }
        }
        if (isSuccess) {
            EventMgr.emit(EventType.PlaceGoods)
            GameMgr.stepNum++
            EventMgr.emit(EventType.GameRefresh)
        } else {
            this._pickedGoods.Visible = true
        }
        // this._pickedGoods.destroy();
        this._pickedGoods = null
        this._holdGoods.destroy()
        this._holdGoods = null
        AudioMgr.playSfx('放下消除物')
    }

    public static get isPicking(): boolean {
        return !!this._pickedGoods
    }

    private onTouchMove(e: EventTouch): void {
        const holdGoods: Node = GameMgr._holdGoods
        if (!isValid(holdGoods)) return
        const uiPos: Vec2 = e.getUILocation()
        uiPos.y += PickOffset
        const localPos: Vec3 = GameMgr._uiTrans.convertToNodeSpaceAR(v3(uiPos.x, uiPos.y, 0))
        holdGoods.setPosition(localPos)

    }

    private onTouchFinish(e: EventTouch): void {
        if (!isValid(GameMgr._holdGoods)) return
        GameMgr.release()
    }

    private static reset(): void {
        this._pickedGoods = null
        this._holdGoods = null
        this.shelveArr = []
        this.shelveLockerArr = []
        this.goodsArr = []
        this.goodsData = {}
        GameMgr.stepNum = 0;
        GameMgr.rightMaxNum = 0;
        GameMgr.useTime = 0;
        GameMgr.itemStatu = 0;

        GameMgr.sureNum = 0;
    }

    public static isModeUnlocked(mode: Mode): boolean {
        return this.unlockedMode.includes(mode)
    }

    public static get isModeAllUnlocked(): boolean {
        return this.unlockedMode.length >= ModeName.length
    }

    public static get isStucked(): boolean {
        for (let i = 0; i < this.shelveArr.length; i++) {
            const shelve: ShelveBase = this.shelveArr[i];
            if (!shelve.isAllSlotOccupied()) return false
        }
        return true
    }

    /**获取主题名称 */
    public static getShowTitle(isToday:boolean = true){
        let ind = GameMgr.mode;

        if (!isToday){
            ind++;
            if (ind >= 3){
                ind = 0;
            }
        }

        return GameMgr.titleArr[ind];
    }

    /**获取是否测试版本 */
    public static getIsTest(){
        return false;
    }

    /**获取是否已通关 */
    public static getIsPassToday(){
        let today = GameUtil.getYearToday();

        if (GameMgr.curPassDay == today){
            return true;
        }
        return false
    }

    /**保存用户信息 */
    public static saveGameUserData(){
        StorageUtil.setObj('gameUserData', GameMgr.gameData);
    }
}

if (PREVIEW) {
    globalThis.GameMgr = GameMgr
}

export class GameUserData{
    /**今日奖励 */
    todayRewardDay:number = 0;
}

